C.S.Burner 🪙 ━►🔥GIT Node
Node / reticulum_mirror / MeshChatX / files / meshchatx / src / frontend / components / settings / PluginsSettingsSection.vue
Displaying Raw • Download
meshchatx/src/frontend/components/settings/PluginsSettingsSection.vue 65ca9ddc823fcc2c8f8653c553b944b85db0875f (65ca9ddc) Text, 26.40 KB
T8b949e<!-- SPDX-License-Identifier: 0BSD -->
Tff7b72<templateTff7b72>
Tff7b72<SettingsSectionBlock
Te6edf3v-show=Ta5d6ff"Ta5d6ffvisibleTa5d6ff"
Te6edf3:title=Ta5d6ff"Te6edf3$tTa5d6ff(Ta5d6ff'Ta5d6ffplugins.settings.titleTa5d6ff'Ta5d6ff)Ta5d6ff"
Te6edf3:description=Ta5d6ff"Te6edf3$tTa5d6ff(Ta5d6ff'Ta5d6ffplugins.settings.descriptionTa5d6ff'Ta5d6ff)Ta5d6ff"
Tff7b72>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffspace-y-4Ta5d6ff"Tff7b72>
Tff7b72<div
Te6edf3class=Ta5d6ff"Ta5d6ffrounded-xl border-2 border-dashed border-gray-300 dark:border-zinc-700 bg-gray-50 dark:bg-zinc-900/40 p-6 text-center transition-colorsTa5d6ff"
Te6edf3:class=Ta5d6ff"Ta5d6ffdragActive ? Ta5d6ff'Ta5d6ffborder-blue-500 bg-blue-50/60 dark:bg-blue-950/20Ta5d6ff'Ta5d6ff : Ta5d6ff'Ta5d6ff'Ta5d6ff"
@dragenter.Te6edf3prevent=Ta5d6ff"Ta5d6ffdragActive = trueTa5d6ff"
@dragover.Te6edf3prevent=Ta5d6ff"Ta5d6ffdragActive = trueTa5d6ff"
@dragleave.Te6edf3prevent=Ta5d6ff"Ta5d6ffdragActive = falseTa5d6ff"
@drop.Te6edf3prevent=Ta5d6ff"Ta5d6ffonDropArchiveTa5d6ff"
Tff7b72>
Tff7b72<p Te6edf3class=Ta5d6ff"Ta5d6fftext-sm font-medium text-gray-800 dark:text-gray-200Ta5d6ff"Tff7b72>
{{ Te6edf3$t("plugins.settings.drag_drop") }}
Tff7b72</p>
Tff7b72<p Te6edf3class=Ta5d6ff"Ta5d6ffmt-1 text-xs text-gray-500 dark:text-gray-400Ta5d6ff"Tff7b72>
{{ Te6edf3$t("plugins.settings.install_zip") }}
Tff7b72</p>
Tff7b72<label Te6edf3class=Ta5d6ff"Ta5d6ffmt-4 inline-flexTa5d6ff"Tff7b72>
Tff7b72<input
Te6edf3ref=Ta5d6ff"Ta5d6fffileInputTa5d6ff"
Te6edf3type=Ta5d6ff"Ta5d6fffileTa5d6ff"
Te6edf3accept=Ta5d6ff"Ta5d6ff.zip,.wasm,application/zip,application/wasmTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffsr-onlyTa5d6ff"
Te6edf3:disabled=Ta5d6ff"Ta5d6ffinstalling || previewingTa5d6ff"
@Te6edf3change=Ta5d6ff"Ta5d6ffonInstallFileTa5d6ff"
Tff7b72/>
Tff7b72<span
Te6edf3class=Ta5d6ff"Ta5d6ffpx-4 py-2 rounded-md bg-blue-600 text-white text-sm cursor-pointer hover:bg-blue-700Ta5d6ff"
Te6edf3:class=Ta5d6ff"Ta5d6ffinstalling || previewing ? Ta5d6ff'Ta5d6ffopacity-60 pointer-events-noneTa5d6ff'Ta5d6ff : Ta5d6ff'Ta5d6ff'Ta5d6ff"
Tff7b72>
{{
installing || previewing
? Te6edf3$t("plugins.settings.installing")
: Te6edf3$t("plugins.settings.choose_file")
}}
Tff7b72</span>
Tff7b72</label>
Tff7b72</div>
Tff7b72<div
Te6edf3v-if=Ta5d6ff"Ta5d6ff!plugins.lengthTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffrounded-lg border border-gray-200 dark:border-zinc-800 px-4 py-8 text-center text-sm text-gray-600 dark:text-gray-400Ta5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.settings.empty_state") }}
Tff7b72</div>
Tff7b72<div
Te6edf3v-for=Ta5d6ff"Ta5d6ffplugin in pluginsTa5d6ff"
Te6edf3:key=Ta5d6ff"Ta5d6ffplugin.idTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffrounded-lg border border-gray-200 dark:border-zinc-800 p-4 space-y-3Ta5d6ff"
Tff7b72>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffflex flex-wrap items-start justify-between gap-3Ta5d6ff"Tff7b72>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffmin-w-0 space-y-2Ta5d6ff"Tff7b72>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffflex flex-wrap items-center gap-2Ta5d6ff"Tff7b72>
Tff7b72<h3 Te6edf3class=Ta5d6ff"Ta5d6fftext-base font-semibold text-gray-900 dark:text-gray-100Ta5d6ff"Tff7b72>{{ plugin.name }}Tff7b72</h3>
Tff7b72<span
Te6edf3class=Ta5d6ff"Ta5d6ffpx-2 py-0.5 rounded-full text-[11px] font-semibold uppercase tracking-wideTa5d6ff"
Te6edf3:class=Ta5d6ff"
Ta5d6ff plugin.enabled
? Ta5d6ff'Ta5d6ffbg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200Ta5d6ff'
Ta5d6ff : Ta5d6ff'Ta5d6ffbg-zinc-200 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300Ta5d6ff'
Ta5d6ff Ta5d6ff"
Tff7b72>
{{
plugin.enabled
? Te6edf3$t("plugins.settings.badge_enabled")
: Te6edf3$t("plugins.settings.badge_disabled")
}}
Tff7b72</span>
Tff7b72<span
Te6edf3v-if=Ta5d6ff"Ta5d6ffplugin.has_frontendTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-2 py-0.5 rounded-full text-[11px] font-semibold uppercase tracking-wide bg-sky-100 text-sky-800 dark:bg-sky-900/30 dark:text-sky-200Ta5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.settings.badge_frontend") }}
Tff7b72</span>
Tff7b72<span
Te6edf3v-if=Ta5d6ff"Ta5d6ffplugin.has_backend && plugin.backend_type === Ta5d6ff'Ta5d6ffpythonTa5d6ff'Ta5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-2 py-0.5 rounded-full text-[11px] font-semibold uppercase tracking-wide bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-200Ta5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.settings.badge_python") }}
Tff7b72</span>
Tff7b72<span
Te6edf3v-else-if=Ta5d6ff"Ta5d6ffplugin.has_backendTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-2 py-0.5 rounded-full text-[11px] font-semibold uppercase tracking-wide bg-violet-100 text-violet-800 dark:bg-violet-900/30 dark:text-violet-200Ta5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.settings.badge_wasm") }}
Tff7b72</span>
Tff7b72<span
Te6edf3v-if=Ta5d6ff"Ta5d6ffplugin.requires_network_fetchTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-2 py-0.5 rounded-full text-[11px] font-semibold uppercase tracking-wide bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-200Ta5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.settings.badge_network") }}
Tff7b72</span>
Tff7b72<span
Te6edf3v-if=Ta5d6ff"Ta5d6ffplugin.signature?.trustedTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-2 py-0.5 rounded-full text-[11px] font-semibold uppercase tracking-wide bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200Ta5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.settings.badge_trusted") }}
Tff7b72</span>
Tff7b72<span
Te6edf3v-else-if=Ta5d6ff"Ta5d6ffplugin.signature?.validTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-2 py-0.5 rounded-full text-[11px] font-semibold uppercase tracking-wide bg-sky-100 text-sky-800 dark:bg-sky-900/30 dark:text-sky-200Ta5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.settings.badge_signed") }}
Tff7b72</span>
Tff7b72<span
Te6edf3v-else-if=Ta5d6ff"Ta5d6ffplugin.signature?.present && !plugin.signature?.validTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-2 py-0.5 rounded-full text-[11px] font-semibold uppercase tracking-wide bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-200Ta5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.settings.badge_invalid_signature") }}
Tff7b72</span>
Tff7b72<span
Te6edf3v-if=Ta5d6ff"Ta5d6ffplugin.tamperedTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-2 py-0.5 rounded-full text-[11px] font-semibold uppercase tracking-wide bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-200Ta5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.settings.badge_tampered") }}
Tff7b72</span>
Tff7b72</div>
Tff7b72<p Te6edf3class=Ta5d6ff"Ta5d6fftext-sm text-gray-600 dark:text-gray-400Ta5d6ff"Tff7b72>{{ plugin.description }}Tff7b72</p>
Tff7b72<p Te6edf3class=Ta5d6ff"Ta5d6fftext-xs text-gray-500 dark:text-gray-500Ta5d6ff"Tff7b72>{{ plugin.id }} · v{{ plugin.version }}Tff7b72</p>
Tff7b72</div>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffflex flex-wrap gap-2Ta5d6ff"Tff7b72>
Tff7b72<button
Te6edf3v-if=Ta5d6ff"Ta5d6ff!plugin.enabledTa5d6ff"
Te6edf3type=Ta5d6ff"Ta5d6ffbuttonTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-3 py-1.5 rounded-md bg-blue-600 text-white text-smTa5d6ff"
Te6edf3:disabled=Ta5d6ff"Ta5d6ffbusyPluginId === plugin.idTa5d6ff"
@Te6edf3click=Ta5d6ff"Ta5d6ffenablePlugin(plugin.id)Ta5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.settings.enable") }}
Tff7b72</button>
Tff7b72<button
v-else
Te6edf3type=Ta5d6ff"Ta5d6ffbuttonTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-3 py-1.5 rounded-md bg-zinc-600 text-white text-smTa5d6ff"
Te6edf3:disabled=Ta5d6ff"Ta5d6ffbusyPluginId === plugin.idTa5d6ff"
@Te6edf3click=Ta5d6ff"Ta5d6ffdisablePlugin(plugin.id)Ta5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.settings.disable") }}
Tff7b72</button>
Tff7b72<button
Te6edf3type=Ta5d6ff"Ta5d6ffbuttonTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-3 py-1.5 rounded-md border border-red-300 text-red-600 text-smTa5d6ff"
Te6edf3:disabled=Ta5d6ff"Ta5d6ffbusyPluginId === plugin.idTa5d6ff"
@Te6edf3click=Ta5d6ff"Ta5d6ffconfirmRemove(plugin)Ta5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.settings.remove") }}
Tff7b72</button>
Tff7b72</div>
Tff7b72</div>
Tff7b72<div Te6edf3v-if=Ta5d6ff"Ta5d6ffpermissionLines(plugin).lengthTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6fftext-sm text-gray-700 dark:text-gray-300Ta5d6ff"Tff7b72>
Tff7b72<p Te6edf3class=Ta5d6ff"Ta5d6fffont-mediumTa5d6ff"Tff7b72>{{ Te6edf3$t("plugins.settings.permissions") }}Tff7b72</p>
Tff7b72<ul Te6edf3class=Ta5d6ff"Ta5d6fflist-disc pl-5Ta5d6ff"Tff7b72>
Tff7b72<li Te6edf3v-for=Ta5d6ff"Ta5d6ffline in permissionLines(plugin)Ta5d6ff" Te6edf3:key=Ta5d6ff"Ta5d6fflineTa5d6ff"Tff7b72>{{ line }}Tff7b72</li>
Tff7b72</ul>
Tff7b72</div>
Tff7b72<div
Te6edf3v-if=Ta5d6ff"Ta5d6ff(plugin.network_endpoints || []).lengthTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6fftext-sm text-gray-700 dark:text-gray-300 space-y-1Ta5d6ff"
Tff7b72>
Tff7b72<p Te6edf3class=Ta5d6ff"Ta5d6fffont-mediumTa5d6ff"Tff7b72>{{ Te6edf3$t("plugins.settings.network_endpoints") }}Tff7b72</p>
Tff7b72<ul Te6edf3class=Ta5d6ff"Ta5d6fflist-disc pl-5Ta5d6ff"Tff7b72>
Tff7b72<li
Te6edf3v-for=Ta5d6ff"Ta5d6ffendpoint in plugin.network_endpointsTa5d6ff"
Te6edf3:key=Ta5d6ff"Ta5d6ffendpointTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6fffont-mono text-xs break-allTa5d6ff"
Tff7b72>
{{ endpoint }}
Tff7b72</li>
Tff7b72</ul>
Tff7b72</div>
Tff7b72<p Te6edf3v-if=Ta5d6ff"Ta5d6ffplugin.auto_disabled_reasonTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6fftext-sm text-amber-700 dark:text-amber-300Ta5d6ff"Tff7b72>
{{ Te6edf3$t("plugins.settings.auto_disabled", { reason: plugin.auto_disabled_reason }) }}
Tff7b72</p>
Tff7b72</div>
Tff7b72<section Te6edf3class=Ta5d6ff"Ta5d6ffrounded-lg border border-amber-300 dark:border-amber-800 p-4 space-y-3Ta5d6ff"Tff7b72>
Tff7b72<divTff7b72>
Tff7b72<h3 Te6edf3class=Ta5d6ff"Ta5d6fftext-sm font-semibold text-gray-900 dark:text-gray-100Ta5d6ff"Tff7b72>
{{ Te6edf3$t("plugins.sideband.title") }}
Tff7b72</h3>
Tff7b72<p Te6edf3class=Ta5d6ff"Ta5d6fftext-xs text-gray-600 dark:text-gray-400 mt-1Ta5d6ff"Tff7b72>
{{ Te6edf3$t("plugins.sideband.description") }}
Tff7b72</p>
Tff7b72</div>
Tff7b72<label Te6edf3class=Ta5d6ff"Ta5d6ffflex items-start gap-2 text-sm text-gray-800 dark:text-gray-200Ta5d6ff"Tff7b72>
Tff7b72<input
Te6edf3v-model=Ta5d6ff"Ta5d6ffsidebandConfig.service_plugins_enabledTa5d6ff"
Te6edf3type=Ta5d6ff"Ta5d6ffcheckboxTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffmt-1 rounded border-gray-300Ta5d6ff"
@Te6edf3change=Ta5d6ff"Ta5d6ffonSidebandMasterToggleTa5d6ff"
Tff7b72/>
Tff7b72<spanTff7b72>{{ Te6edf3$t("plugins.sideband.master_enable") }}Tff7b72</span>
Tff7b72</label>
Tff7b72<label Te6edf3class=Ta5d6ff"Ta5d6ffflex items-start gap-2 text-sm text-gray-800 dark:text-gray-200Ta5d6ff"Tff7b72>
Tff7b72<input
Te6edf3v-model=Ta5d6ff"Ta5d6ffsidebandConfig.command_plugins_enabledTa5d6ff"
Te6edf3type=Ta5d6ff"Ta5d6ffcheckboxTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffmt-1 rounded border-gray-300Ta5d6ff"
Te6edf3:disabled=Ta5d6ff"Ta5d6ff!sidebandConfig.service_plugins_enabledTa5d6ff"
Tff7b72/>
Tff7b72<spanTff7b72>{{ Te6edf3$t("plugins.sideband.command_enable") }}Tff7b72</span>
Tff7b72</label>
Tff7b72<label Te6edf3class=Ta5d6ff"Ta5d6ffblock text-sm text-gray-800 dark:text-gray-200 space-y-1Ta5d6ff"Tff7b72>
Tff7b72<spanTff7b72>{{ Te6edf3$t("plugins.sideband.path") }}Tff7b72</span>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffflex flex-col sm:flex-row gap-2Ta5d6ff"Tff7b72>
Tff7b72<input
Te6edf3v-model=Ta5d6ff"Ta5d6ffsidebandConfig.command_plugins_pathTa5d6ff"
Te6edf3type=Ta5d6ff"Ta5d6fftextTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffw-full rounded-md border border-gray-300 dark:border-zinc-700 bg-white dark:bg-zinc-900 px-3 py-1.5 text-sm min-w-0Ta5d6ff"
Te6edf3:disabled=Ta5d6ff"Ta5d6ff!sidebandConfig.service_plugins_enabledTa5d6ff"
Tff7b72/>
Tff7b72<button
Te6edf3type=Ta5d6ff"Ta5d6ffbuttonTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-3 py-1.5 rounded-md border border-gray-300 dark:border-zinc-600 text-sm shrink-0 min-h-[44px]Ta5d6ff"
Te6edf3:disabled=Ta5d6ff"Ta5d6ff!sidebandConfig.service_plugins_enabled || sidebandBusyTa5d6ff"
Te6edf3:title=Ta5d6ff"Te6edf3$tTa5d6ff(Ta5d6ff'Ta5d6ffplugins.sideband.browse_titleTa5d6ff'Ta5d6ff)Ta5d6ff"
@Te6edf3click=Ta5d6ff"Ta5d6ffpickSidebandPluginsDirectoryTa5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.sideband.browse") }}
Tff7b72</button>
Tff7b72</div>
Tff7b72</label>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffflex flex-wrap gap-2Ta5d6ff"Tff7b72>
Tff7b72<button
Te6edf3type=Ta5d6ff"Ta5d6ffbuttonTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-3 py-1.5 rounded-md bg-blue-600 text-white text-smTa5d6ff"
Te6edf3:disabled=Ta5d6ff"Ta5d6ffsidebandBusyTa5d6ff"
@Te6edf3click=Ta5d6ff"Ta5d6ffsaveSidebandConfigTa5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.sideband.save") }}
Tff7b72</button>
Tff7b72<button
Te6edf3type=Ta5d6ff"Ta5d6ffbuttonTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffpx-3 py-1.5 rounded-md border border-gray-300 dark:border-zinc-600 text-smTa5d6ff"
Te6edf3:disabled=Ta5d6ff"Ta5d6ffsidebandBusyTa5d6ff"
@Te6edf3click=Ta5d6ff"Ta5d6ffreloadSidebandTa5d6ff"
Tff7b72>
{{ Te6edf3$t("plugins.sideband.reload") }}
Tff7b72</button>
Tff7b72</div>
Tff7b72<div Te6edf3v-if=Ta5d6ff"Ta5d6ffsidebandPlugins.lengthTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6ffspace-y-2Ta5d6ff"Tff7b72>
Tff7b72<p Te6edf3class=Ta5d6ff"Ta5d6fftext-sm font-medium text-gray-900 dark:text-gray-100Ta5d6ff"Tff7b72>
{{ Te6edf3$t("plugins.sideband.loaded") }}
Tff7b72</p>
Tff7b72<ul Te6edf3class=Ta5d6ff"Ta5d6ffspace-y-2Ta5d6ff"Tff7b72>
Tff7b72<li
Te6edf3v-for=Ta5d6ff"Ta5d6ffitem in sidebandPluginsTa5d6ff"
Te6edf3:key=Ta5d6ff"Ta5d6ffitem.pathTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffrounded-md border border-gray-200 dark:border-zinc-700 px-3 py-2 text-xs space-y-1Ta5d6ff"
Tff7b72>
Tff7b72<p Te6edf3class=Ta5d6ff"Ta5d6fffont-medium text-gray-800 dark:text-gray-200Ta5d6ff"Tff7b72>
{{ item.name }}
Tff7b72<span Te6edf3class=Ta5d6ff"Ta5d6ffuppercase text-gray-500Ta5d6ff"Tff7b72>({{ item.type }})Tff7b72</span>
Tff7b72</p>
Tff7b72<p Te6edf3v-if=Ta5d6ff"Ta5d6ffitem.errorTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6fftext-red-600 dark:text-red-400Ta5d6ff"Tff7b72>{{ item.error }}Tff7b72</p>
Tff7b72<ul
Te6edf3v-if=Ta5d6ff"Ta5d6ff(item.security_findings || []).lengthTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6fflist-disc pl-4 text-gray-600 dark:text-gray-400Ta5d6ff"
Tff7b72>
Tff7b72<li Te6edf3v-for=Ta5d6ff"Ta5d6fffinding in item.security_findingsTa5d6ff" Te6edf3:key=Ta5d6ff"Ta5d6fffinding.idTa5d6ff"Tff7b72>
{{ finding.message }}
Tff7b72</li>
Tff7b72</ul>
Tff7b72</li>
Tff7b72</ul>
Tff7b72</div>
Tff7b72</section>
Tff7b72</div>
Tff7b72<PluginInstallDialog
Te6edf3:open=Ta5d6ff"Ta5d6ffdialogOpenTa5d6ff"
Te6edf3:preview=Ta5d6ff"Ta5d6ffinstallPreviewTa5d6ff"
Te6edf3:confirming=Ta5d6ff"Ta5d6ffinstallingTa5d6ff"
@Te6edf3cancel=Ta5d6ff"Ta5d6ffcancelInstallPreviewTa5d6ff"
@Te6edf3confirm=Ta5d6ff"Ta5d6ffconfirmInstallPreviewTa5d6ff"
Tff7b72/>
Tff7b72</SettingsSectionBlock>
Tff7b72</template>
Tff7b72<scriptTff7b72>
import SettingsSectionBlock from "./SettingsSectionBlock.vue";
import PluginInstallDialog from "./PluginInstallDialog.vue";
import ToastUtils from "../../js/ToastUtils";
import DialogUtils from "../../js/DialogUtils";
import ElectronUtils from "../../js/ElectronUtils";
import AndroidBridge from "../../js/rnode/AndroidBridge";
import { permissionLabel } from "../../js/plugins/pluginPermissions.js";
import { pluginHost } from "../../js/plugins/PluginHost.js";
import { onWsEvent, offWsEvent } from "../../js/registries/wsEventRegistry.js";
export default {
name: "PluginsSettingsSection",
components: { SettingsSectionBlock, PluginInstallDialog },
props: {
visible: {
type: Boolean,
default: true,
},
},
data() {
return {
plugins: [],
dragActive: false,
installing: false,
previewing: false,
busyPluginId: null,
dialogOpen: false,
installPreview: null,
pendingArchive: null,
sidebandBusy: false,
sidebandPlugins: [],
sidebandConfig: {
service_plugins_enabled: false,
command_plugins_enabled: false,
command_plugins_path: "",
},
};
},
mounted() {
void this.refresh();
void this.refreshSideband();
this.onPluginDisabled = (payload) => {
if (payload?.event === "plugin.disabled") {
ToastUtils.warning(this.$t("plugins.settings.kill_switch", { reason: payload?.payload?.reason || "" }));
pluginHost.unloadPlugin(payload?.plugin_id);
void this.refresh();
}
};
onWsEvent("plugin.event", this.onPluginDisabled);
},
beforeUnmount() {
offWsEvent("plugin.event", this.onPluginDisabled);
},
methods: {
currentLocale() {
return this.$i18n?.locale?.value || this.$i18n?.locale || "en";
},
permissionLines(plugin) {
const granted = plugin.granted_permissions || plugin.declared_permissions || [];
if (!granted.length) {
return [this.$t("plugins.permissions.none")];
}
return granted.map((id) => permissionLabel(id, (key) => this.$t(key)));
},
async refresh() {
const response = await window.api.get("/api/v1/plugins");
this.plugins = response.data?.plugins || [];
},
async refreshSideband() {
const response = await window.api.get("/api/v1/sideband-plugins");
const config = response.data?.config || {};
this.sidebandConfig = {
service_plugins_enabled: Boolean(config.service_plugins_enabled),
command_plugins_enabled: Boolean(config.command_plugins_enabled),
command_plugins_path: config.command_plugins_path || "",
};
this.sidebandPlugins = response.data?.plugins || [];
},
onSidebandMasterToggle() {
if (this.sidebandConfig.service_plugins_enabled) {
const ok = window.confirm(this.$t("plugins.sideband.danger_confirm"));
if (!ok) {
this.sidebandConfig.service_plugins_enabled = false;
}
}
},
async pickSidebandPluginsDirectory() {
if (!this.sidebandConfig.service_plugins_enabled) {
return;
}
const picked = await ElectronUtils.pickDirectory();
if (picked) {
this.sidebandConfig.command_plugins_path = picked;
ToastUtils.success(this.$t("plugins.sideband.path_picked"));
return;
}
if (ElectronUtils.isElectron()) {
return;
}
const android = new AndroidBridge();
let initial = this.sidebandConfig.command_plugins_path || "";
if (android.isAvailable()) {
const suggested = android.getSidebandPluginsDefaultPath();
if (suggested && !initial) {
initial = suggested;
}
}
const entered = await DialogUtils.prompt(
initial
? `${this.$t("plugins.sideband.path_prompt")}\n${initial}`
: this.$t("plugins.sideband.path_prompt")
);
if (entered != null && String(entered).trim()) {
this.sidebandConfig.command_plugins_path = String(entered).trim();
ToastUtils.success(this.$t("plugins.sideband.path_picked"));
}
},
async saveSidebandConfig() {
this.sidebandBusy = true;
try {
const response = await window.api.post("/api/v1/sideband-plugins/config", {
service_plugins_enabled: this.sidebandConfig.service_plugins_enabled,
command_plugins_enabled: this.sidebandConfig.command_plugins_enabled,
command_plugins_path: this.sidebandConfig.command_plugins_path || null,
});
this.sidebandPlugins = response.data?.plugins || [];
ToastUtils.success(this.$t("plugins.sideband.saved"));
} catch (error) {
ToastUtils.error(
this.$t("plugins.settings.install_failed", { reason: error?.message || String(error) })
);
} finally {
this.sidebandBusy = false;
}
},
async reloadSideband() {
this.sidebandBusy = true;
try {
const response = await window.api.post("/api/v1/sideband-plugins/reload");
this.sidebandPlugins = response.data?.plugins || [];
ToastUtils.success(this.$t("plugins.sideband.reloaded"));
} catch (error) {
ToastUtils.error(
this.$t("plugins.settings.install_failed", { reason: error?.message || String(error) })
);
} finally {
this.sidebandBusy = false;
}
},
async enablePlugin(pluginId) {
this.busyPluginId = pluginId;
try {
await window.api.post(`/api/v1/plugins/${encodeURIComponent(pluginId)}/enable`);
await pluginHost.loadEnabledPlugins(window.api, this.currentLocale());
await this.refresh();
ToastUtils.success(this.$t("plugins.settings.enabled"));
} catch (error) {
ToastUtils.error(
this.$t("plugins.settings.install_failed", { reason: error?.message || String(error) })
);
await this.refresh();
} finally {
this.busyPluginId = null;
}
},
async disablePlugin(pluginId) {
this.busyPluginId = pluginId;
try {
await window.api.post(`/api/v1/plugins/${encodeURIComponent(pluginId)}/disable`);
pluginHost.unloadPlugin(pluginId);
await this.refresh();
ToastUtils.info(this.$t("plugins.settings.disabled"));
} finally {
this.busyPluginId = null;
}
},
confirmRemove(plugin) {
const prompt = this.$t("plugins.settings.confirm_remove", { name: plugin.name || plugin.id });
if (!window.confirm(prompt)) {
return;
}
void this.removePlugin(plugin.id);
},
async removePlugin(pluginId) {
this.busyPluginId = pluginId;
try {
await window.api.delete(`/api/v1/plugins/${encodeURIComponent(pluginId)}`);
pluginHost.unloadPlugin(pluginId);
await this.refresh();
ToastUtils.info(this.$t("plugins.settings.removed"));
} finally {
this.busyPluginId = null;
}
},
async beginInstallPreview(file) {
if (!file) {
return;
}
this.previewing = true;
this.pendingArchive = file;
try {
const formData = new FormData();
formData.append("archive", file);
const response = await window.api.post("/api/v1/plugins/preview", formData);
this.installPreview = response.data;
this.dialogOpen = true;
} catch (error) {
this.pendingArchive = null;
this.installPreview = null;
ToastUtils.error(
this.$t("plugins.settings.install_failed", { reason: error?.message || String(error) })
);
} finally {
this.previewing = false;
this.dragActive = false;
if (this.$refs.fileInput) {
this.$refs.fileInput.value = "";
}
}
},
cancelInstallPreview() {
this.dialogOpen = false;
this.installPreview = null;
this.pendingArchive = null;
},
async confirmInstallPreview({ grantedPermissions, trustPublisher, signer, signerName }) {
if (!this.pendingArchive) {
this.cancelInstallPreview();
return;
}
this.installing = true;
try {
if (trustPublisher && signer) {
await window.api.post("/api/v1/plugins/trusted-publishers", {
identity: signer,
name: signerName || signer,
});
}
const formData = new FormData();
formData.append("archive", this.pendingArchive);
formData.append("granted_permissions", JSON.stringify(grantedPermissions || []));
await window.api.post("/api/v1/plugins/install", formData);
await this.refresh();
ToastUtils.success(this.$t("plugins.settings.installed"));
this.cancelInstallPreview();
} catch (error) {
ToastUtils.error(
this.$t("plugins.settings.install_failed", { reason: error?.message || String(error) })
);
} finally {
this.installing = false;
}
},
async onInstallFile(event) {
const file = event.target.files?.[0];
await this.beginInstallPreview(file);
},
async onDropArchive(event) {
this.dragActive = false;
const file = event.dataTransfer?.files?.[0];
await this.beginInstallPreview(file);
},
},
};
Tff7b72</script>
Served by rngit 1.5.2 - Generated in 0.04s